package edu.gdpu.memory.stringtable;

/**
 * @author mazebin
 * @date 2021年 07月15日 12:14:07
 */
public class StringTableTest3 {
    public static void main(String[] args) {
        String a="a";
        String b ="b";
        String c=a+b;
        String ab="ab";

        System.out.println(ab == a+b);//false
        //为什么上面会是false,因为通过字节码分析+号底层是使用
        // StringBuilder.append方法实现字符串拼接，然后通过StringBuilder.toString返回，
        // 本质上生成了一个新的匿名对象，而==比较的是地址，因此输出false
        //另外这里我还注意到一个dup指令（复制栈顶一个字长内容，并压入栈内）
        //原因：JVM在执行new指令时，将会开辟一块新的内存区域而后将引用地址压入栈内。
        //而后面执行init方法时，jvm会将这块内存区域从栈中弹出,这是如果栈内不保存一个引用地址，程序员将无法拿到这块地址，也就无法对这个对象进行操作了

        System.out.println(ab.equals(a+b));//true
/**
 字节码：
 public static void main(java.lang.String[]);
 descriptor: ([Ljava/lang/String;)V
 flags: ACC_PUBLIC, ACC_STATIC
 Code:
 stack=4, locals=4, args_size=1
 0: ldc           #2                  // String a
 2: astore_1
 3: ldc           #3                  // String b
 5: astore_2
 6: ldc           #4                  // String ab
 8: astore_3
 9: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
 12: aload_3                          //将ab从变量3中弹到栈顶
 13: new           #6                  // class java/lang/StringBuilder
 16: dup
 17: invokespecial #7                  // Method java/lang/StringBuilder."<init>":()V
 20: aload_1
 21: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
 24: aload_2
 25: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
 28: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
 31: if_acmpne     38                //如果两个对象引用不相等，则跳转
 34: iconst_1
 35: goto          39
 38: iconst_0
 39: invokevirtual #10                 // Method java/io/PrintStream.println:(Z)V
 42: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
 45: aload_3
 46: new           #6                  // class java/lang/StringBuilder
 49: dup                                //复制栈顶部一个字长内容，并压入站内
 50: invokespecial #7                  // Method java/lang/StringBuilder."<init>":()V
 53: aload_1
 54: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
 57: aload_2
 58: invokevirtual #8                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
 61: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
 64: invokevirtual #11                 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
 67: invokevirtual #10                 // Method java/io/PrintStream.println:(Z)V
 70: return
 LineNumberTable:
 line 9: 0
 line 10: 3
 line 11: 6
 line 12: 9
 line 13: 42
 line 15: 70
 LocalVariableTable:
 Start  Length  Slot  Name   Signature
 0      71     0  args   [Ljava/lang/String;
 3      68     1     a   Ljava/lang/String;
 6      65     2     b   Ljava/lang/String;

 */
    }
}
